#include "device.h"
#include "component.h"

/* 调试打印接口 */
#define BATTERY_LOG(format, ...)    OSAL_LOG(format, ##__VA_ARGS__)

/* 电池电量更新事件 */
#define EVENT_BATTERY_UPDATE (0X00000001)

#define VHW_IIC_BAT vIIC_5
#define IIC_ADDR_BAT 0x55

#define CMD_READ_BAT_TEMPER 0x08        // 电芯温度   
#define CMD_READ_BAT_VOLTAGE 0x09       //电芯电压
#define CMD_READ_BAT_CAPACITY 0x10      //电芯容量    
#define CMD_READ_BAT_CYCLES 0x17        //电芯循环次数

/* 电池电量更新事件的处理周期 */
#define BATTERY_UPDATE_EVT_PROC_CYCLE (3000)

#pragma pack(1)
typedef struct
{
    uint16_t temp;     //电池温度
    uint16_t vol;     //电池电压
    uint16_t bat;     //电池电量
    uint16_t times;   //电池循环次数
} Bat_Info_t;
#pragma pack()

static Bat_Info_t batMsg = {0,0,100,0};
static Bat_Info_t lastBattery = {0,0,100,0};

/**
  * @brief  crc8计算
  * @note   多项式0x07
  * @param  ptr：数据域
  * @param  len：数据长度
  * @return crc值
  */
static uint8_t crc8_cal(uint8_t *ptr, uint16_t len)
{
    unsigned char i;
    unsigned char crc = 0x00;

    while (len--)
    {
        crc ^= *ptr++;
        for (i = 8; i > 0; --i)
        {
            if (crc & 0x80)
                crc = (crc << 1) ^ 0x07;
            else
                crc = (crc << 1);
        }
    }

    return (crc);
}

//读取电池循环次数
static int32_t Battery_Read_Bat_Cycles(uint8_t *data)
{
    int32_t ret = 1;
    uint8_t ori_data[10] = {IIC_ADDR_BAT<<1,CMD_READ_BAT_CYCLES,(IIC_ADDR_BAT<<1)|1};
    if (Device_Write(VHW_IIC_BAT, &ori_data[1], 1, IIC_ADDR_BAT) == 0)
    {
        ret = Device_Read(VHW_IIC_BAT, &ori_data[3], 3, IIC_ADDR_BAT);
    } 
        
    /* crc校验 */
    if (ret == 0)
    {
        uint8_t crc = crc8_cal(ori_data, 5);
        for(uint8_t i=0;i<6;i++)
        {
            printf("%x ",ori_data[i]);
        }
        printf("crc:%x ",crc);
        if (crc != ori_data[5])
        {
            BATTERY_LOG("crc err\r\n");
            ret = 2;
        }
        else
        {
            memcpy(data, &ori_data[3], 2);
        }
    }
    else
    {
        // BATTERY_LOG("iic communication  err\r\n");
    }

}

//读取电池容量
static int32_t Battery_Read_Bat_Capacity(uint8_t *data)
{
    int32_t ret = 1;
    uint8_t ori_data[10] = {IIC_ADDR_BAT<<1,CMD_READ_BAT_CAPACITY,(IIC_ADDR_BAT<<1)|1};
    if (Device_Write(VHW_IIC_BAT, &ori_data[1], 1, IIC_ADDR_BAT) == 0)
    {
        ret = Device_Read(VHW_IIC_BAT, &ori_data[3], 3, IIC_ADDR_BAT);
    } 
        
    /* crc校验 */
    if (ret == 0)
    {
        uint8_t crc = crc8_cal(ori_data, 5);
        // for(uint8_t i=0;i<6;i++)
        // {
        //     BATTERY_LOG("%x ",ori_data[i]);
        // }
        // BATTERY_LOG("crc:%x ",crc);
        if (crc != ori_data[5])
        {
            BATTERY_LOG("crc err\r\n");
            ret = 2;
        }
        else
        {
            memcpy(data, &ori_data[3], 2);
        }
    }
    else
    {
        // BATTERY_LOG("iic communication  err\r\n");
    }
    return ret;
}

static void Battery_Process(void)
{
    Bat_Info_t bat_inf;

    if (Battery_Read_Bat_Capacity((uint8_t *)&bat_inf.bat) == 0)
    {
        // bat_inf.temp = OSAL_SWAP16(bat_inf.temp);
        // bat_inf.vol = OSAL_SWAP16(bat_inf.vol);
        bat_inf.bat = OSAL_SWAP16(bat_inf.bat);
        // bat_inf.times = OSAL_SWAP16(bat_inf.times);

        batMsg.vol = (uint8_t)bat_inf.vol;
        batMsg.bat = (uint8_t)bat_inf.bat;
        BATTERY_LOG("bat is %d,last:%d\r\n",batMsg.bat,lastBattery.bat);
        if (batMsg.vol != lastBattery.vol || batMsg.bat < lastBattery.bat)
        {
            lastBattery.bat = batMsg.bat;
            lastBattery.vol = batMsg.vol;
            BATTERY_LOG("updata: %d\r\n",bat_inf.bat);
            OSAL_MessagePublish(&batMsg.bat, sizeof(batMsg.bat));
        }
    }
}

static uint8_t Battery_Get(void)
{
	BATTERY_LOG("battery : %d\r\n",batMsg.bat);
	return batMsg.bat;
}

/**
  * @brief  Battery任务函数
  *
  * @note   1.任务函数内不能写阻塞代码
  *         2.任务函数每次运行只处理一个事件
  *         
  * @param  event：当前任务的所有事件
  *
  * @return 返回未处理的事件
  */
static uint32_t Battery_Task(uint32_t event)
{
    /* 系统启动事件 */
    if (event & EVENT_SYS_START)
    {
        BATTERY_LOG("Bttery task start\r\n");
        OSAL_EventRepeatCreate(COMP_BATTERY, EVENT_BATTERY_UPDATE, BATTERY_UPDATE_EVT_PROC_CYCLE, EVT_PRIORITY_LOW);

        /* 注册对外开放的API接口 */
        SYS_API(Battery_Get);

        return (event ^ EVENT_SYS_START);
    }

    /* 系统休眠事件 */
    if (event & EVENT_SYS_SLEEP)
    {
        Device_Disable(vIIC_5);
        OSAL_EventDelete(COMP_BATTERY, EVENT_BATTERY_UPDATE);
        return (event ^ EVENT_SYS_SLEEP);
    }

    /* 电池电量更新事件 */
    if (event & EVENT_BATTERY_UPDATE)
    {
        Battery_Process();
        return (event ^ EVENT_BATTERY_UPDATE);
    }
    return 0;
}
COMPONENT_TASK_EXPORT(COMP_BATTERY, Battery_Task, 0);
